package com.ukefu.webim.web.handler.apps.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.ukefu.core.UKDataContext;
import com.ukefu.util.Menu;
import com.ukefu.util.UKTools;
import com.ukefu.webim.service.acd.ServiceQuene;
import com.ukefu.webim.service.es.ContactsRepository;
import com.ukefu.webim.service.es.OnlineUserESRepository;
import com.ukefu.webim.service.impl.AgentUserService;
import com.ukefu.webim.service.repository.AgentServiceRepository;
import com.ukefu.webim.service.repository.AgentUserContactsRepository;
import com.ukefu.webim.service.repository.AgentUserRepository;
import com.ukefu.webim.service.repository.AgentUserTaskRepository;
import com.ukefu.webim.service.repository.ChatMessageRepository;
import com.ukefu.webim.service.repository.OnlineUserHisRepository;
import com.ukefu.webim.service.repository.OnlineUserRepository;
import com.ukefu.webim.service.repository.OrganRepository;
import com.ukefu.webim.service.repository.ServiceSummaryRepository;
import com.ukefu.webim.service.repository.SessionTypeRepository;
import com.ukefu.webim.service.repository.SysDicRepository;
import com.ukefu.webim.service.repository.TagRelationRepository;
import com.ukefu.webim.service.repository.TagRepository;
import com.ukefu.webim.service.repository.UserRepository;
import com.ukefu.webim.service.repository.WeiXinUserRepository;
import com.ukefu.webim.web.handler.Handler;
import com.ukefu.webim.web.model.AgentService;
import com.ukefu.webim.web.model.AgentServiceSummary;
import com.ukefu.webim.web.model.AgentUser;
import com.ukefu.webim.web.model.AgentUserContacts;
import com.ukefu.webim.web.model.AgentUserTask;
import com.ukefu.webim.web.model.OnlineUser;
import com.ukefu.webim.web.model.SessionConfig;
import com.ukefu.webim.web.model.SessionType;
import com.ukefu.webim.web.model.SysDic;
import com.ukefu.webim.web.model.WeiXinUser;

@Controller
@RequestMapping("/apps/monitor")
public class MonitorServiceController extends Handler{
	
	@Autowired
	private AgentServiceRepository agentServiceRes ;
	
	@Autowired
	private OrganRepository organRes ;
	
	@Autowired
	private UserRepository userRes ;
	
	@Autowired
	private OnlineUserESRepository onlineUserESRes; 
	
	@Autowired
	private OnlineUserRepository onlineUserRes; 
	
	@Autowired
	private ServiceSummaryRepository serviceSummaryRes; 
	
	@Autowired
	private OnlineUserHisRepository onlineUserHisRes;
	
	@Autowired
	private WeiXinUserRepository weiXinUserRes;
	
	@Autowired
	private TagRepository tagRes ;
	
	@Autowired
	private TagRelationRepository tagRelationRes ;
	
	@Autowired
	private ChatMessageRepository chatMessageRepository ;
	
	@Autowired
	private ContactsRepository contactsRes ;
	
	@Autowired
	private AgentUserContactsRepository agentUserContactsRes ;
	
	@Autowired
	private SessionTypeRepository sessionTypeRes ;
	
	@Autowired
	private SysDicRepository sysDicRes ;
	
	@Autowired
	private AgentUserService agentUserRes ;
	
	@Autowired
	private AgentUserRepository agentUserRepository;
	
	@Autowired
	private AgentUserTaskRepository agentUserTaskRes;
	
	
	@RequestMapping("/index")
    @Menu(type = "service" , subtype = "monitor" )
    public ModelAndView index(ModelMap map , HttpServletRequest request ,final String status ,final boolean showsensitive ,final boolean showtimeout,final boolean showinquenetimeout) {
		this.desktop(map, request, status,showsensitive,showtimeout,showinquenetimeout) ;
        return request(super.createAppsTempletResponse("/apps/service/monitor/index"));
    }
	
	
	
	@RequestMapping("/online/index")
    @Menu(type = "service" , subtype = "monitor" )
    public ModelAndView online(ModelMap map , HttpServletRequest request , final String userid , String agentservice , @Valid String channel) {
		if(!StringUtils.isBlank(userid)){
			map.put("inviteResult", UKTools.getWebIMInviteResult(onlineUserRes.findByOrgiAndUserid(super.getOrgi(request), userid))) ;
			map.put("tagRelationList", tagRelationRes.findByUseridAndOrgi(userid,super.getOrgi(request))) ;
			map.put("onlineUserHistList", onlineUserHisRes.findByUseridAndOrgi(userid, super.getOrgi(request))) ;
			map.put("agentServicesAvg", onlineUserRes.countByUserForAvagTime(super.getOrgi(request), UKDataContext.AgentUserStatusEnum.END.toString(),userid)) ;
			
			//List<AgentService> agentServiceList = agentServiceRes.findByUseridAndOrgi(userid, super.getOrgi(request)) ; 
			final String orgi = super.getOrgi(request);
			Page<AgentService> agentServiceList= agentServiceRes.findAll(new Specification<AgentService>(){
				@Override
				public Predicate toPredicate(Root<AgentService> root, CriteriaQuery<?> query,
						CriteriaBuilder cb) {
					List<Predicate> list = new ArrayList<Predicate>();  
					list.add(cb.equal(root.get("orgi").as(String.class), orgi));
					list.add(cb.equal(root.get("userid").as(String.class),userid));
					
					Predicate[] p = new Predicate[list.size()];  
					return cb.and(list.toArray(p));   
				}}, new PageRequest(0, 10000, Sort.Direction.DESC, new String[] { "servicetime" }));
			
			map.put("agentServiceList", agentServiceList) ;
			if(agentServiceList.getContent().size()>0){
				map.put("serviceCount", Integer
						.valueOf(this.agentServiceRes
								.countByUseridAndOrgiAndStatus(userid, super.getOrgi(request),
										UKDataContext.AgentUserStatusEnum.END.toString())));
				
				AgentService agentService = agentServiceList.getContent().get(0) ;
				if(!StringUtils.isBlank(agentservice)){
					for(AgentService as : agentServiceList.getContent()){
						if(as.getId().equals(agentservice)){
							agentService = as ; break ;
						}
					}
				}
				
				if(agentService!=null){
					Page<AgentServiceSummary> summaryList = this.serviceSummaryRes.findByOrgiAndUserid(super.getOrgi(request), userid , new PageRequest(0, super.getPs(request), Sort.Direction.DESC, new String[] { "createtime" }));
					map.addAttribute("summaryList", summaryList) ;
					map.addAttribute("tagsSummary", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , UKDataContext.ModelType.SUMMARY.toString())) ;
				}
				
				List<AgentUserContacts> agentUserContactsList = agentUserContactsRes.findByUseridAndOrgi(userid, super.getOrgi(request)) ;
				if(agentUserContactsList.size() > 0){
					AgentUserContacts agentUserContacts = agentUserContactsList.get(0) ;
					map.put("contacts", contactsRes.findByIdAndOrgi(agentUserContacts.getContactsid(),super.getOrgi(request))) ;
				}
				
				map.put("tags", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , UKDataContext.ModelType.USER.toString())) ;
				map.put("curAgentService", agentService) ;
				
				
				map.put("agentUserMessageList", chatMessageRepository.findByAgentserviceidAndOrgi(agentService.getId() , super.getOrgi(request), new PageRequest(0, 50, Direction.DESC , "updatetime")));
			}
			
			if(UKDataContext.ChannelTypeEnum.WEIXIN.toString().equals(channel)){
				List<WeiXinUser> weiXinUserList = weiXinUserRes.findByOpenidAndOrgi(userid, super.getOrgi(request)) ;
				if(weiXinUserList.size() > 0){
					WeiXinUser weiXinUser = weiXinUserList.get(0) ;
					map.put("weiXinUser",weiXinUser);
				}
			}else if(UKDataContext.ChannelTypeEnum.WEBIM.toString().equals(channel)){
				List<OnlineUser> onlineUserList =  onlineUserESRes.findByUseridAndOrgi(userid, super.getOrgi(request)) ;
				if(onlineUserList.size() >0){
					map.put("onlineUser", onlineUserList.get(0)) ;
				}
			}
			map.put("agentUser", agentUserRes.findByUseridAndOrgi(userid, super.getOrgi(request))) ;
			map.put("curagentuser", agentUserRes.findByUseridAndOrgi(userid, super.getOrgi(request))) ;
			map.put("monitoragentuser", agentUserTaskRes.findByUseridAndOrgi(userid, super.getOrgi(request))) ;
			
			//文字客服
			AgentService agentService = agentServiceRes.findByIdAndOrgi(agentservice, super.getOrgi(request));
			SysDic sysDic = sysDicRes.findByCode("sessionWords");
			if(agentService != null &&sysDic != null){
				List<SessionType> sessionTypeList = sessionTypeRes.findByOrgiAndCtype(super.getOrgi(request), sysDic.getId());
				for(SessionType  ses : sessionTypeList){
					if(!StringUtils.isBlank(agentService.getSessiontype()) && ses.getId().equals(agentService.getSessiontype())){
						map.addAttribute("agentSessionType", ses.getName());
					}
				}
			}
			map.addAttribute("agentService", agentService);
			map.addAttribute("userid", userid);
			map.addAttribute("agentservice", agentservice);
			map.addAttribute("channel", channel);
		}
		SessionConfig sessionConfig = ServiceQuene.initSessionConfig(super.getOrgi(request)) ;
    	map.put("sessionConfig", sessionConfig) ;
        return request(super.createRequestPageTempletResponse("/apps/service/monitor/agent"));
    }
	
	@RequestMapping({ "/agent/end" })
	@Menu(type = "service" , subtype = "monitor" )
	public ModelAndView end(HttpServletRequest request, @Valid String userid)
			throws Exception {
		AgentUser agentUser = agentUserRepository.findByIdAndOrgi(userid, super.getOrgi(request));
		if(agentUser!=null && super.getUser(request).getId().equals(agentUser.getAgentno())){
			ServiceQuene.deleteAgentUser(agentUser, super.getOrgi(request) , UKDataContext.EndByType.AGENT.toString());
			if(!StringUtils.isBlank(agentUser.getAgentserviceid())){
				AgentService agentService = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), super.getOrgi(request)) ;
				if(agentService!=null) {
					agentService.setStatus(UKDataContext.AgentUserStatusEnum.END.toString());
					agentServiceRes.save(agentService) ;
				}
			}
		}
		return request(super
				.createRequestPageTempletResponse("redirect:/apps/monitor/index.html"));
	}
	
	@RequestMapping("/desktop")
    @Menu(type = "service" , subtype = "monitor" )
    public ModelAndView desktop(ModelMap map , HttpServletRequest request ,final String status ,final boolean showsensitive ,final boolean showtimeout,final boolean showinquenetimeout) {
		final String orgi = super.getOrgi(request);
		SessionConfig sessionConfig = ServiceQuene.initSessionConfig(super.getOrgi(request)) ;
		Page<AgentUserTask> page = null ;
		if (!showinquenetimeout) {
			page = agentUserTaskRes.findAll(new Specification<AgentUserTask>(){
				@Override
				public Predicate toPredicate(Root<AgentUserTask> root, CriteriaQuery<?> query,CriteriaBuilder cb) {
					List<Predicate> list = new ArrayList<Predicate>();  
					if (!showsensitive && !showtimeout && !showinquenetimeout) {
						if(!StringUtils.isBlank(status)) {
							list.add(cb.equal(root.get("status").as(String.class), status)) ;
						}else {
							//咨询中的会话
							list.add(cb.equal(root.get("status").as(String.class), UKDataContext.AgentUserStatusEnum.INSERVICE.toString())) ;
						}
					}
					if (showsensitive) {
						//触发敏感词的会话
						list.add(cb.or(cb.notEqual(root.get("agentfrewords").as(int.class), 0), cb.notEqual(root.get("servicefrewords").as(int.class), 0))) ;
					}
					if (showtimeout) {
						//会话超时的会话
						list.add(cb.lessThan(root.get("servicetime").as(Date.class), UKTools.getLastTime(ServiceQuene.initSessionConfig(orgi).getSestimeouts()))) ;
						list.add(cb.equal(root.get("status").as(String.class), UKDataContext.AgentUserStatusEnum.INSERVICE.toString())) ;
					}
					
					list.add(cb.equal(root.get("orgi").as(String.class), orgi)) ;
					
					
					Predicate[] p = new Predicate[list.size()];  
				    return cb.and(list.toArray(p));   
				}
			},new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime")) ;
		}else {
			//排队超时的会话
			page = onlineUserRes.findByInquenetimeoutFromAgentUserTask(sessionConfig.getInquenetimeouts(),orgi,new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime"));
		}
		
		map.put("showsensitive", showsensitive) ;
		map.put("showtimeout", showtimeout) ;
		map.put("showinquenetimeout", showinquenetimeout) ;
		
		map.put("agentServiceList", page) ;
		map.put("organlist",organRes.findByOrgi(super.getOrgi(request)));
		map.put("userlist",userRes.findByOrgiAndDatastatus(super.getOrgi(request), false));
		map.put("status",StringUtils.isNotBlank(status) ? status : UKDataContext.AgentUserStatusEnum.INSERVICE.toString());
		Map<String,Long> agentUserTaskCount = onlineUserRes.countAgentUserTask(super.getOrgi(request)) ;
		//底下
		long inservicecount = agentUserTaskCount.get("inservicecount");//咨询中的会话
		long inquenecount = agentUserTaskCount.get("inquenecount");//等待接入的会话
		long frewordscount = agentUserTaskCount.get("frewordscount");//坐席敏感词报警的会话
		map.put("monitorcount", inservicecount+inquenecount) ; //监控会话数量
		map.put("inservicecount", inservicecount) ;
		map.put("inquenecount",inquenecount) ;
		map.put("frewordscount",frewordscount) ;
		
		//上方
		long agentfrewordssum = agentUserTaskCount.get("agentfrewordssum")==null?0L:agentUserTaskCount.get("agentfrewordssum");//坐席敏感词报警
		long servicefrewordssum = agentUserTaskCount.get("servicefrewordssum")==null?0L:agentUserTaskCount.get("servicefrewordssum"); //访客敏感词报警
		long msgtimeoutagentsum = agentUserTaskCount.get("msgtimeoutagentsum")==null?0L:agentUserTaskCount.get("msgtimeoutagentsum"); //坐席会话超时次数
		long avgreplytime = onlineUserRes.avgByAvgreplytimeFromAgentUserTask(super.getOrgi(request))==null?0L:onlineUserRes.avgByAvgreplytimeFromAgentUserTask(super.getOrgi(request));//平均响应超时时长
		long agentservicetimeoutavg = 0 ;
		long sessiontimeoutsum =0 ;
		if (sessionConfig.isSestimeout()) {
			List<AgentUserTask> timeoutList = agentUserTaskRes.findByServicetimeLessThanAndStatusAndOrgi(UKTools.getLastTime(sessionConfig.getSestimeouts()) ,UKDataContext.AgentUserStatusEnum.INSERVICE.toString(),sessionConfig.getOrgi()) ;
			if (timeoutList != null && timeoutList.size() > 0) {
				for(AgentUserTask aut : timeoutList) {
					agentservicetimeoutavg += (new Date().getTime() -aut.getServicetime().getTime())/1000-sessionConfig.getSestimeouts() ;
				}
				agentservicetimeoutavg = agentservicetimeoutavg/timeoutList.size() ;
			}
//			long agentservicetimeoutavg = onlineUserRes.avgByAgentservicetimeoutFromAgentUserTask(super.getOrgi(request))==null?0L:onlineUserRes.avgByAgentservicetimeoutFromAgentUserTask(super.getOrgi(request));//平均超时时长
//			long sessiontimeoutsum = agentUserTaskCount.get("sessiontimeoutsum")==null?0L:agentUserTaskCount.get("sessiontimeoutsum"); //会话超时次数
			sessiontimeoutsum = (long)timeoutList.size() ; //会话超时次数
		}
		long quenetimeoutcount = 0;
		long queueavg = 0;
		if (sessionConfig.isInquenetimeout()) {
//			先注释掉
			queueavg = onlineUserRes.avgByQueueavgFromAgentUserTask(super.getOrgi(request))==null?0L:onlineUserRes.avgByQueueavgFromAgentUserTask(super.getOrgi(request));//平均排队时长
			quenetimeoutcount = onlineUserRes.countByInquenetimeoutFromAgentUserTask(sessionConfig.getInquenetimeouts(),orgi)==null?0L:onlineUserRes.countByInquenetimeoutFromAgentUserTask(sessionConfig.getInquenetimeouts(),orgi);//排队超时次数
		}
		long invalidcount = agentUserTaskCount.get("invalidcount");//无效会话次数
		long queneoutcount = agentUserTaskCount.get("queneoutcount");//访客排队中离开 次数
		long agentoutcount = agentUserTaskCount.get("agentoutcount");//进入会话后离开 次数
		long satisfactionalarmscount = agentUserTaskCount.get("satisfactionalarmscount")==null?0L:agentUserTaskCount.get("satisfactionalarmscount");//满意度报警次数
		long invitevalscount = agentUserTaskCount.get("invitevalscount")==null?0L:agentUserTaskCount.get("invitevalscount");//邀请评价次数
		long resptimeoutscount = agentUserTaskCount.get("resptimeoutscount")==null?0L:agentUserTaskCount.get("resptimeoutscount");//响应超时 次数
		map.put("agentfrewordssum", agentfrewordssum) ;
		map.put("servicefrewordssum", servicefrewordssum) ;
		map.put("msgtimeoutagentsum", msgtimeoutagentsum) ;
		map.put("agentservicetimeoutavg", agentservicetimeoutavg) ;
		map.put("avgreplytime", avgreplytime) ;
		map.put("sessiontimeoutsum", sessiontimeoutsum) ;
		map.put("queueavg", queueavg) ;
		map.put("quenetimeoutcount", quenetimeoutcount) ;
		map.put("invalidcount", invalidcount) ;
		map.put("queneoutcount", queneoutcount) ;
		map.put("agentoutcount", agentoutcount) ;
		map.put("satisfactionalarmscount", satisfactionalarmscount) ;
		map.put("invitevalscount", invitevalscount) ;
		map.put("resptimeoutscount", resptimeoutscount) ;
		map.put("warns", agentfrewordssum+servicefrewordssum+satisfactionalarmscount) ;
    	map.put("sessionConfig", sessionConfig) ;
        return request(super.createRequestPageTempletResponse("/apps/service/monitor/content"));
    }
	
}